#include "FreetypeWrapper.h"
#include "log/log.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <log/log.h>
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <string>
#include "WMarkConfig.h"

namespace android
{

    FreetypeWrapper::FreetypeWrapper()
    {
        WMarkConfig *wmarkConfig = WMarkConfig::getInstance();

        mEnable = wmarkConfig->isEnableWatermark();
        mWidth = wmarkConfig->getWmarkImageWidth();
        mHeight = wmarkConfig->getWmarkImageHeight();
        mFontSzie = wmarkConfig->getFontSzie();
        mFontLibName = wmarkConfig->getFontLibPath();
        wmarkConfig->getPenXY(&mPenX, &mPenY);
        setlocale(LC_CTYPE, "zh_CN.utf8");
    }

    FreetypeWrapper::~FreetypeWrapper()
    {
    }

    void FreetypeWrapper::draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y, u_int8_t **image)
    {
        FT_Int i, j, p, q;
        FT_Int x_max = x + bitmap->width;
        FT_Int y_max = y + bitmap->rows;

        /* for simplicity, we assume that `bitmap->pixel_mode' */
        /* is `FT_PIXEL_MODE_GRAY' (i.e., not a bitmap font)   */

        for (i = x, p = 0; i < x_max; i++, p++)
        {
            for (j = y, q = 0; j < y_max; j++, q++)
            {
                if (i < 0 || j < 0 ||
                    i >= mWidth || j >= mHeight)
                    continue;
                image[j][i] |= bitmap->buffer[q * bitmap->width + p];
                // ALOGD("%s %d image[%d][%d]=%d\n", __func__, __LINE__, j, i, image[j][i]);
            }
        }
    }

    int FreetypeWrapper::text2img(string mark_text, u_int8_t **img_data, int img_w, int img_h)
    {
        if (includeChinese(mark_text.c_str())) {
            return textChinese2img(mark_text, img_data, img_w, img_h);
        } else {
            return textEnglish2img(mark_text, img_data, img_w, img_h);
        }
    }

    wchar_t *FreetypeWrapper::toWchar(wchar_t **ppDest, const char *pSrc)
    {
        int len = 0;
        int ret = 0;

        len = strlen(pSrc);
        if (len <= 1)
            return *ppDest;

        *ppDest = (wchar_t *)malloc(len * sizeof(wchar_t));

        /*如果第一个参数为NULL,则可以用来返回宽字符的长度*/
        // printf("len:%ld\n", mbstowcs(NULL, pSrc, 0) + 1);

        ret = mbstowcs(*ppDest, pSrc, len);

        return *ppDest;
    }

    int FreetypeWrapper::includeChinese(char const *str)
    {
        char c;
        while (1)
        {
            c = *str++;
            if (c == 0)
                break;    //如果到字符串尾则说明该字符串没有中文字符
            if (c & 0x80) //如果字符高位为1且下一字符高位也是1则有中文字符
                if (*str & 0x80)
                    return 1;
        }
        return 0;
    }
    int FreetypeWrapper::textEnglish2img(string mark_text, u_int8_t **img_data, int img_w, int img_h)
    {
        if ((img_w * img_h) < (mWidth * mHeight) || !mEnable)
        {
            return -1;
        }
        FT_Library library;
        FT_Face face;

        FT_GlyphSlot slot;
        FT_Matrix matrix; /* transformation matrix */
        FT_Vector pen;    /* untransformed origin  */
        FT_Error error;

        char const *filename;
        char const *text;

        double angle;
        int target_height;
        int n, num_chars;

        filename = mFontLibName.c_str();
        text = mark_text.c_str();
        num_chars = strlen(text);
        angle = (0 / 360) * 3.14159 * 2; /* use 25 degrees     */
        target_height = mHeight;

        error = FT_Init_FreeType(&library); /* initialize library */
        /* error handling omitted */

        error = FT_New_Face(library, filename, 0, &face); /* create face object */
        /* error handling omitted */

        /* use 24pt at 100dpi */
        error = FT_Set_Char_Size(face, mFontSzie * 64, 0,
                                 100, 0); /* set character size */
        /* error handling omitted */

        /* cmap selection omitted;                                        */
        /* for simplicity we assume that the font contains a Unicode cmap */

        slot = face->glyph;

        /* set up matrix */
        matrix.xx = (FT_Fixed)(cos(angle) * 0x10000L);
        matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
        matrix.yx = (FT_Fixed)(sin(angle) * 0x10000L);
        matrix.yy = (FT_Fixed)(cos(angle) * 0x10000L);

        // 改变生成图片 字体的位置
        pen.x = mPenX * 64;
        pen.y = (target_height - mFontSzie - mPenY) * 64;

        for (n = 0; n < num_chars; n++)
        {
            /* set transformation */
            FT_Set_Transform(face, &matrix, &pen);

            /* load glyph image into the slot (erase previous one) */
            error = FT_Load_Char(face, text[n], FT_LOAD_RENDER);
            if (error)
                continue; /* ignore errors */

            /* now, draw to our target surface (convert position) */
            // printf("bitmap_left(%d), bitmap_top(%d)\n", slot->bitmap_left, slot->bitmap_top);
            // printf("bitmap_width(%d), bitmap_rows(%d)\n", slot->bitmap.width, slot->bitmap.rows);
            draw_bitmap(&slot->bitmap,
                        slot->bitmap_left,
                        target_height - slot->bitmap_top, img_data);

            /* increment pen position */
            pen.x += slot->advance.x;
            pen.y += slot->advance.y;
        }

        FT_Done_Face(face);
        FT_Done_FreeType(library);

        return 0;

    }
    int FreetypeWrapper::textChinese2img(string mark_text, u_int8_t **img_data, int img_w, int img_h)
    {
        if ((img_w * img_h) < (mWidth * mHeight) || !mEnable)
        {
            return -1;
        }
        FT_Library library;
        FT_Face face;

        FT_GlyphSlot slot;
        FT_Matrix matrix; /* transformation matrix */
        FT_Vector pen;    /* untransformed origin  */
        FT_Error error;

        char const *filename;
        char const *text;

        double angle;
        int target_height;
        int n, num_chars;

        wchar_t *wcharText;
        int wcharLen;

        filename = mFontLibName.c_str();
        text = mark_text.c_str();
        num_chars = strlen(text);
        angle = (0 / 360) * 3.14159 * 2; /* use 25 degrees     */
        target_height = mHeight;

        toWchar(&wcharText, text);
        wcharLen = wcslen(wcharText);

        error = FT_Init_FreeType(&library); /* initialize library */
        /* error handling omitted */

        error = FT_New_Face(library, filename, 0, &face); /* create face object */
        /* error handling omitted */

        /* use 24pt at 100dpi */
        error = FT_Set_Char_Size(face, mFontSzie * 64, 0,
                                 100, 0); /* set character size */
        /* error handling omitted */

        /* cmap selection omitted;                                        */
        /* for simplicity we assume that the font contains a Unicode cmap */

        slot = face->glyph;

        /* set up matrix */
        matrix.xx = (FT_Fixed)(cos(angle) * 0x10000L);
        matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
        matrix.yx = (FT_Fixed)(sin(angle) * 0x10000L);
        matrix.yy = (FT_Fixed)(cos(angle) * 0x10000L);

        // 改变生成图片 字体的位置
        pen.x = mPenX * 64;
        pen.y = (target_height - mFontSzie - mPenY) * 64;

        for (n = 0; n < wcharLen; n++)
        {
            if (!wcharText) {
                ALOGV("wcharText == NULL");
                break;
            }
            /* set transformation */
            FT_Set_Transform(face, &matrix, &pen);

            /* load glyph image into the slot (erase previous one) */
            error = FT_Load_Char(face, (unsigned int)wcharText[n], FT_LOAD_RENDER);
            if (error)
                continue; /* ignore errors */

            /* now, draw to our target surface (convert position) */
            // printf("bitmap_left(%d), bitmap_top(%d)\n", slot->bitmap_left, slot->bitmap_top);
            // printf("bitmap_width(%d), bitmap_rows(%d)\n", slot->bitmap.width, slot->bitmap.rows);
            draw_bitmap(&slot->bitmap,
                        slot->bitmap_left,
                        target_height - slot->bitmap_top, img_data);

            /* increment pen position */
            pen.x += slot->advance.x;
            pen.y += slot->advance.y;
        }

        if (wcharText) {
            free(wcharText);
        }

        FT_Done_Face(face);
        FT_Done_FreeType(library);

        return 0;
    }

}
